import { _decorator, ColliderComponent, Component, instantiate, isValid, ITriggerEvent, Node, Prefab, RigidBodyComponent, Vec2, Vec3 } from 'cc';
import { Ball } from './Ball';
import { App } from '../../App';
import { RigidBody } from 'cc';
import { EventConst } from '../../common/Common';
import { CylinderCollider } from 'cc';
import { SpriteFrame } from 'cc';
import { GameBaseModel } from './GameBaseModel';
import { find } from 'cc';
import { UIOpacity } from 'cc';
import { tween } from 'cc';
import { Tween } from 'cc';
import UtilTool from '../../tools/UtilTool';
import { GameBaseLogic } from './GameBaseLogic';
const { ccclass, property } = _decorator;


@ccclass('Role')
export class Role extends Component {
    
    @property(Prefab)
    ball : Prefab = null;
    
    @property(Prefab)
    inRoleAnimPrefab : Prefab = null // 球进洞动画

    // @property(Number)
    // inRoleDistance : Number = 6.5 // 判断进洞的距离

    @property(Number)
    roleID : number = 1 // 洞的ID

    public roleNumber = 0 // 洞的编号 (因为在预制体里面roleID不能赋值0，所以这里重新定义了一个字段)

    inRoleAnimNode : Node = null

    onLoad(): void {
        this.roleNumber = this.roleID - 1
    }

    start() {
        
        this.initTestRoleBall()
        this.node.getComponent(ColliderComponent).on('onTriggerStay', this.onTriggerRole, this);
        
    }

    initTestRoleBall() {

        if(!this.ball) {
            return
        }

        let b = instantiate(this.ball);
        b.parent = this.node.parent;
        b.setPosition(22.219, 5, -14.321);
        
        // b.getComponent(Ball).init(9);

        // let force = new Vec3(17, 0, -20).multiplyScalar(5)
        // let force = new Vec3(30, 0, -20).multiplyScalar(1.1)

        // b.getComponent(RigidBodyComponent).applyImpulse(force, new Vec3(0, 0, 0));
        // b.getComponent(RigidBodyComponent).applyImpulse(force, new Vec3(0, 0, 0));
        
        let force = new Vec3(0, 0, -20).multiplyScalar(1.1)
        b.getComponent(RigidBodyComponent).applyImpulse(force, new Vec3(0, 0, 0));
        
    }

    private onTriggerRole(event: ITriggerEvent) {

        let ball = event.otherCollider.node;

        let ballX = ball.worldPosition.x;
        let ballZ = ball.worldPosition.z;

        let distance = new Vec2(ballX - this.node.worldPosition.x, ballZ - this.node.worldPosition.z).length();
        
        // 球进洞
        let ballCtrl = ball.getComponent(Ball)
        // let inDistance = 12 - (ballCtrl.getSize()/2)

        let inDistance = this.getSize()/2 // 球心进到洞口的边缘距离

        
        
        // 半个球进入洞口就算进洞了
        if (distance < inDistance && !ballCtrl.isHasInRole) {
            // UtilTool.printLog("test inDistance", distance)
            
            ballCtrl.isHasInRole = true

            // 球进洞声音
            App.Audio.playOneShot("ballDrop")      

            // 掌声
            let gameLogic : GameBaseLogic = App.Model.gameLogic as GameBaseLogic
            if (gameLogic && gameLogic.curPlayUser.isBelognMine(ballCtrl.number)) {
                App.Audio.playOneShot("ballDrop_clap") 
            }

            // 记录进洞编号(同一个洞只记录一次)
            let oneRoleNumber = null // 没有记录过这个洞编号则赋值
            if(gameLogic && gameLogic.roleInballList.indexOf(this.roleNumber)==-1) {
                gameLogic.roleInballList.push(this.roleNumber)
                oneRoleNumber = this.roleNumber
            }

            let ballNumber = ball.getComponent(Ball).number

            let callEnd = ()=> {
                App.Event.emit(EventConst.BALL_IN_ROLE, ballNumber, ball, this);
                App.Event.emit(EventConst.BALL_IN_ROLE_SCORE, ballNumber, oneRoleNumber, this);
            }

            this.playInRole3dAnim(ball, callEnd)

            return;
        }

    }

    getSize() : number {
        let radius = this.node.getComponent(CylinderCollider).radius;
        let size = radius * 2 * this.node.worldScale.x;

        return size
        
    }

    // 播放球进洞的3d效果
    playInRole3dAnim(ball, callEnd) {

        let rigidBody : RigidBody = ball.getComponent(RigidBody)
        let ballCtrl = ball.getComponent(Ball)

        let roleRadius = 3
        let ballRadius = ballCtrl.getSize()/2

        // 指向球心
        let curPos = ball.worldPosition
        let centerPos = this.node.worldPosition
        
        // 以球刚好完全掉进洞时的点为起点，逆时针转两圈
        let length = ballRadius * 2

        let toEndVec2 = new Vec2(centerPos.x, centerPos.z).subtract2f(curPos.x, curPos.z).normalize().multiplyScalar(length)
        let endX = curPos.x + toEndVec2.x
        let endZ = curPos.z + toEndVec2.y
        let endPos = new Vec3(endX, curPos.y, endZ)
        let toEndVec3 = endPos.clone().subtract(curPos).multiplyScalar(5)
        rigidBody.setLinearVelocity(toEndVec3);
        
        let angle = toEndVec2.angle(new Vec2(0, 1))

        let defaultScaleVec3 = ball.worldScale.clone()
        let defaultScale = defaultScaleVec3.x
        let defaultY = ball.worldPosition.y
        let defaultSize = ballCtrl.getSize()

        // 去掉阴影
        ballCtrl.meshRenderer.shadowCastingMode = 0

        tween(ball)
        .delay(0.1).call(()=>{
            ball.interAngle = ball.eulerAngles
            rigidBody.setAngularVelocity(new Vec3(0, 0, 0))
            rigidBody.setLinearVelocity(new Vec3(0, 0, 0))
        })
        .to(0.5, {}, {  // 转圈并且缩小
            onUpdate(target : Role, ratio : number) {
                let newAngle = angle + Math.PI * 4  * ratio // 转两圈
                
                let endScale = defaultScale/5*3 - 0.2
                let curScale = endScale + (defaultScale-endScale)*(1-ratio)
                ball.worldScale = new Vec3(curScale, curScale, curScale)

                let scaleSubSize = (defaultSize - (curScale*defaultSize)/defaultScale)/2
                let x = Math.sin(newAngle) * (roleRadius + scaleSubSize)
                let y = Math.cos(newAngle) * (roleRadius + scaleSubSize)
                let newWorldPos = new Vec3(centerPos.x + x, ball.worldPosition.y, centerPos.z + y)
                ball.worldPosition = newWorldPos
                
            }
        }).call(()=>{
            ball.worldScale = defaultScaleVec3
            ball.worldPosition.y = defaultY
            ballCtrl.isHasInRole = false
            ballCtrl.meshRenderer.shadowCastingMode = 1
            ballCtrl.hide()
            callEnd && callEnd()
        }).start()

    }

    playInRoleAnim() { // 同时放大和透明度

        if(!this.inRoleAnimNode) {
            this.inRoleAnimNode = instantiate(this.inRoleAnimPrefab);
            this.inRoleAnimNode.parent = (App.Model.gameView as GameBaseModel).gameLayer;
        }

        let model : GameBaseModel = App.Model.gameView as GameBaseModel
        let rolePos = model.World3DToUI(this.node.worldPosition)
        
        Tween.stopAllByTarget(this.inRoleAnimNode)
        // this.inRoleAnimNode.active = true
        this.inRoleAnimNode.getComponent(UIOpacity).opacity = 0
        this.inRoleAnimNode.position = new Vec3(rolePos.x, rolePos.y, 0)

        tween(this.inRoleAnimNode).delay(0.1)
        .call(()=>{
            this.inRoleAnimNode.active = true
        })
        .to(0.2, {}, {
            easing: 'elasticInOut',
            onUpdate:(target : Node, ratio : number) => {
                target.getComponent(UIOpacity).opacity = 216 * ratio
                target.scale = new Vec3(ratio, ratio, 1)
                // target.angle = -150 * ratio
            }
        }).delay(0.1).call(()=>{
            this.inRoleAnimNode.active = false
        }).start()

    }

    update(deltaTime: number) {
        
    }

    protected onDestroy(): void {
        Tween.stopAllByTarget(this.node)
        Tween.stopAllByTarget(this.inRoleAnimNode)
    }
    
}

